﻿/*
 * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved.
 */

#ifndef BURNCTRL_H
#define BURNCTRL_H

#include <windows.h>
#include <winsock.h>
#include <QTextEdit>
#include <QProgressBar>
#include <QThread>
#include <QMutex>
#include <QPlainTextEdit>
#include <QObject>
#include "DataConvertor.h"
#include "SerialPort/PortManager.h"
#include "BurnCtrlWorker.h"
#include "BurnToolCommon/OperationLog.h"
#include "BurnToolCommon/ProductVersion.h"
#include "BurnToolCommon/StringClass.h"
#include "BurnDlg/BurnDlg.h"
class MemoryOperation {
public:
    MemoryOperation();
    ~MemoryOperation();
    bool Seek(qint64 mOffset);
    qint64 Pos() const;
    qint64 Read(BYTE *data, qint64 maxlen);
    void SetEncrypt(BYTE *buffer, DWORD bufferLen);
    void Init();
public:
    BYTE *encryptBuffer;
    DWORD encryptBufferLen;
    qint64 offset;
};

namespace BurnCtrlTimer {
struct TimerInfo {
    TimerInfo(U32 event, UINT *timerId)
        : event(event),
          timerId(timerId)
    {
    }
    U32 event {0};
    UINT *timerId {nullptr};
};
}

class CSLock {
public:
    CSLock() noexcept
    {
        InitializeCriticalSection(&m_cs);
    };
    virtual ~CSLock()
    {
        DeleteCriticalSection(&m_cs);
    };
    void EntryCS()
    {
        EnterCriticalSection(&m_cs);
    };
    void LeaveCs()
    {
        LeaveCriticalSection(&m_cs);
    };
private:
    CRITICAL_SECTION m_cs;
};

struct SingleLineWritingInfo {
    unsigned int len;
    char singleLineData[3];
    SingleLineWritingInfo()
        : len(0) {
    }
};


class BurnCtrl : public QObject {
    Q_OBJECT
public:
    explicit BurnCtrl(ChipType type = ChipType::WIFI5GNB, QObject *parent = nullptr);
    ~BurnCtrl() override;

    enum BurnCmdType {
        BURN_CMD,
        OTHER,
        END,
        LOADER,
        ERASE_ALL,
        UNKNOWN,
    };

    virtual void ResetUIAndFSM();
    void SetShutDown();
    virtual void SendCtrl();
    virtual void StartConnectSetting();
    virtual bool ConfigComPort();
    virtual bool ConfigTcpPort();
    virtual bool UpdateComSettingWithoutClose();
    virtual void YmodemPrepareIntialPacket(PBYTE &pBurnFileInfo, int &pktLen);
    virtual void ProcessReceiveData(PBYTE data, unsigned int &dataLen);
    void FsmWaitInitAck(QString &strData);
    virtual void BurnCtrlCancel();
    void FsmWaitFinalAck(QString &strData);
    void FsmWaitEotC(QString &strData);
    void FsmWaitZeroAck(QString &strData);
    void FsmWaitStartC(QString &strData);
    virtual void ResetBurnState();
    virtual void WriteToPort(const char *data, int len);
    virtual bool UpdateComSetting(UINT mBaud, UINT mDatabits, UINT mStopbits, QSerialPort::Parity mParity,
                                  UINT mFlowctrl);
    virtual void SetIpSetting(QString mIpAddr, UINT mIpPort);
    virtual void SetPortType(unsigned int type);
    void GetComSetting(int &mBaud, int &mDatabits, int &mStopbits,
                       QSerialPort::Parity &mParity, int &mFlowctrl) const;
    virtual void SetIsCancel(BOOL mIsCancel);
    virtual U32 StartBurn();
    virtual U32 GetBurnFileInfo();

    virtual void SwitchBoot(BootType type);
    virtual U32 SendBurnCmd();
    virtual void InitBurnCmd();
    virtual void InitBurnCmdByArray(const QMap<int, BIN_INFO> &mInfoArray);
    virtual void SetLoaderInfo(QString loaderFile, int loaderSize);
    virtual void StartUpload(QString output, U32 addr, U32 size);
    virtual void ReadEfuse(U32 addr, U32 size);
    virtual void SetEraseMode(int eraseMode);
    virtual void SetOnlyEraseAll(bool eraseAll);
    virtual void ResetByCmd();
    virtual void AtReset(QString);
    virtual void SwitchToDfu();
    virtual void EraseAllByCmd();
    virtual void SetProgressRange();
    virtual void TimeoutProcess();
    virtual void FwpkgVersion(QString version);
    void SetBurnTimeout(UINT timeout);
    virtual void SetResult(unsigned int mResult);
    void ShowResult();
    void SetResultFromAToB(unsigned int resultA, unsigned int resultB);
    unsigned int GetResult() const;
    BurnCtrl::BurnCmdType GetCurrentCmdType();
    QString GetCurrentFilePath();
    void SetTimerByFsm();
    bool MakeTimerInfoByFsm(U32& timeout, bool& isPeriod);
    bool MakeTimerInfoByFsmInner(U32& timeout);
    void YmodemNextPacket();
    void SetFilePath(int index, QString strPath);
    QString GetFilePath();
    void SetFsm(HI_BURN_FSM mFsm);
    virtual void UpdateProgress(UINT progress);
    void NotifyState(UINT ret, UINT progress);
    void WifiState();
    void ResetByMode();
    void SetOneTimeBurnFlag(bool mIsOneTimeBurn);
    void SetAutoBurnFlag(bool mIsAutoBurn);
    void SetLoaderDfu(bool mIsLoaderDfu);
    void SetUsbDeviceInfo(HidDeviceInfo usbDeviceInfo);
    void SetBoardIPAddress(const IPInfo &ipinfo);
    void SetIPAddress(const QString &ip);
    void SetAutoDisconnectFlag(bool mIsAutoDisconnect);
    void SetReopenComFlag(bool mIsReopenCom);
    void SetFileInfo(QString mtSrFilePath);
    void SetComNum(int num);
    void RegisteResultEdit(bool isMultiple);
    virtual void OutputString(QString editStr);
    void SetEditErrorString(QString editStr);
    void ClosePort();
    bool IsComOpen() const;
    HI_BURN_FSM GetBurnFsm() const;
    virtual void StartConnect();
    void SetBurnDlg(BurnDlg::BurnDlg *dlg);
    void SetSecConn(bool mIsSecConn);
    bool IsSecConn() const;
    virtual bool IsBusy();
    void EnterCS();
    void LeaveCS();
    void EnterCSSend();
    void LeaveCSSend();
    void EnterCSEdit();
    void LeaveCSEdit();
    void SetOnlyBurnToolLog(BOOL mOnlyBurnToolLog);
    void SetForceReadFlag(BOOL isForceRead);
    bool GetForceReadFlag() const;
    void SetResultByOwnerFlag(BOOL mIsResultByOwner);
    void SetForceReadTime(UINT mForceReadTime);
    unsigned int GetForceReadTime() const;
    void SetConfirmConnectSleepTime(UINT time);
    void SetConfirmConnectWaitTime(UINT time);
    void SetPeriod(int period);

    static VOID CALLBACK BurnCtrlCommonTimerHandler(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1,
                                                    DWORD_PTR dw2);
    bool TimerHandle();
    bool TimerHandleInner();
    void TimerHandleInnerSub();
    void BurnCtrlCommonTimerHandlerTestSub1();
    void BurnCtrlCommonTimerHandlerTestSub2();
    bool StartWiteMonitoring();
    bool IsNeedRetry() const;
    void SendRetryFlag();
    void SetUseExactTimer(BOOL useExactTimer);

    static BurnCtrl *GetRunningItem(UINT id);
    static void RemoveRunningItem(UINT id);
    static void SetRunningItem(UINT id, BurnCtrl *point);
    static void RemoveParamPoint(UINT id);
    static void SetParamPoint(UINT id, const BurnCtrlTimer::TimerInfo *point);
    unsigned int AddLogToBuffer(const QString &inputLog) const;
    unsigned int AddLog(QString input) const;

    BootType GetBootType() const;
    int GetPeriod() const;
    UINT GetConnectConfirmSleepTimeout() const;
    UINT GetConnectConfirmWaitTimeout() const;
    DWORD GetWiteThreadId() const;
    U32 GetMultiBurnTotalNum() const;
    U32 GetMultiBurnNumPerLine() const;
    bool GetMultiBurnIndenpendentBurn() const;
    bool GetMultiBurnReopenCom() const;
    void SetMultiBurnTotalNum(unsigned int mTotalNum);
    void SetMultiBurnNumPerLine(unsigned int mNumPerLine);
    void SetMultiBurnIndenpendentBurn(bool indenpendent);
    void SetResetAfterBurn(bool reset);
    void SetYModemEachPackageSize(int packageSize);
    unsigned int GetYModemEachPackageSize() const;
    void SetIsWiteThreadAlive(bool mIsWiteThreadAlive);
    void InsertPlainText(const QString &editStr);
    void ClearPlainText();
    void ReplacePlainText(const QString &oldText, const QString &newText);
    void MergeCurrentCharFormat(const QTextCharFormat &fmt);
    void SetProgressRange(int minimum, int maximum);
    void SetProgressValue(unsigned int progress);
    BurnCtrlWorkerClass::BurnCtrlWorker *GetBurnCtrlWorker();
    void SetMultiBurnFlag();
    void SetIsFirstBurnStart(bool firstBurnStart);
    virtual void EraseAll();
    virtual void CommonAction1();
    virtual void CommonAction2();
    virtual void CommonAction3();
    void DisconnectSignalSendMsg() const;
    void ConnectSignalSendMsg() const;
    void SetExportAfterBurn(bool mIsExport);
    void SetExportPath(QString mExportTarget);
    void SetExportAddr(QString mExportAddr);
    void SetExportSize(QString mExportSize);
    void SetIsEncrypt(bool mIsEncrypt);
    void SetEncryptBufferLen(DWORD bufferLen);
    void SetEncryptBuffer(BYTE *buffer);
    void SetIsResetAfterSuccess(bool mIsResetAfterSuccess);
    bool GetIsResetAfterSuccess() const;
    void FsmBurnWaitInterAck(const unsigned char *data, const unsigned int &dataLen, QString &strData);

    QString GetBurnCurrentTime() const;
    QString GetBurnComToStr() const;
    QMap<int, BIN_INFO> GetBurnArray();
    void SetBurnFileName(QString mStrFileName) const;
    void SetBurnStartTime(QString strSartTime) const;
    void SetBurnEndTime(QString strEndTime) const;
    void SetBurnComNum(QString strComNum) const;
    void SetBurnBinFile(QMap<int, BIN_INFO> mInfoArray) const;
    void SetBurnResult(int mResult) const;
    void SetReadEfuse(bool mReadEfuse);
    void SetStartBit(QString mStartBit);
    void SetBitWidth(QString mBitWidth);
    void SetPackageSize(UINT packageSize);
    virtual void SetHSANTypeFlag(QString type);
    void RecordIntoFile() const;
    void RecordFile(QByteArray str) const;
    void CloseFile() const;
    void SetIsAutoDfu(DfuBurnMode mode);
    void SetIsSwitchAfterLoader(bool mIsSwitchAfterLoader);
    bool GetIsSwitchAfterLoader() const;
    void SetChipModel(int mChipModel);
    void SetMcuConfig(McuConfig mMcuConfig);
    void SetTransmissionMode(int mode);
    void SetJtagSwd(McuJtagSwd mcuJtagSwd);
    void SetChipId(McuChipId mcuChipId);
    void SetMainStartAddress(MainStartAddrInfo info);
    void SetBurnPath(QString path);
    void SetIsReadBack(bool readBack);
    void SetIsRun(bool run);
    virtual void McuReopen();
    void SetUSBSerialName(const QString& mSerialName);
    virtual void SetIsEmptyFlash(bool);
    void SetEraseConfig(unsigned int cbEraseConfig, const QVector<EraseConfig> &vecErase);
    void SetInfoStartAddress(int info);
    void RmoveTimerKey();
    QString GetFwpkgVersion();
signals:
    void SignalSwitchDfu(WPARAM wParam, LPARAM lParam);
    void SignalAutoDisconnect(WPARAM wParam, LPARAM lParam);
    void SignalInsertPlainText(const QString &editStr);
    void SignalClearPlainText();
    void SignalReplacePlainText(const QString &oldText, const QString &newText);
    void SignalMergeCurrentCharFormat(const QTextCharFormat &fmt);
    void SignalSetProgressRange(int minimum, int maximum);
    void SignalSetProgressValue(int progress);
    void SignalOpenComFail();
    void SignalBurnFileFinish();
    void SignalBurnFileFailed();
    void SignalNotifyState(unsigned int, unsigned int);
    void SignalShowQMessageBox(QString);
    void SignalExportSuccess();
    void SignalExportfail();
    void SignalSendMsg(long int msgId, WPARAM wParam, LPARAM lParam);
    void SignalEraseSuccess();
    void SignalEraseFail();
    void SignalCloseApp();
    void SignalSetLog(QString logs, bool isShowTime, QColor color);
    void SignalSetConnectStatus(bool isEnable);
    void SignalSetTips(const QString &title, const QString &text);
    void SignalChangeChipModeByChipId(QString &chipName, uint chipId);
    void SignalSetParameterInfoList(QByteArray);
    void SignalAddSerialNum(const QString &serialNum);
public slots:
    void SlotStartConnectTimerOut();
    virtual long int SlotCommunication(WPARAM srcData, LPARAM srcLen);
    void SlotKillAllTimer();
    void SlotResetUIAndFSM();
    void SlotInitBurnCmd();
    void SlotStartConnect();
    void SlotResetBurnState();
    void SlotBurnCtrlCommonTimerHandler2();
    void SlotBurnCtrlCommonTimerHandlerTest();
    void SlotConfigComPort();
    virtual void SlotSetResult(WPARAM srcData);
    void SlotShowResult();
    void SlotSetResultFromAToB(WPARAM wParam, LPARAM lParam);
    void SlotExitApp(WPARAM wParam, LPARAM lParam) const;
    virtual void SlotCloseJlink();
    virtual void SlotExport(WPARAM wParam, LPARAM lParam);
    void SlotCommonAction1();
    void SlotCommonAction2();
    void SlotCommonAction3();
    void SlotEraseAll();
    void SlotMcuReopen();
    void SlotStartBurn();
    virtual void SlotEraseMemory(WPARAM data, LPARAM len);
    void SetSramAddrInfo(SramAddrInfo info);
    virtual void SlotGetParameter();
    virtual void SlotSetParameter();
    virtual void SetTotalDigits(int);
    virtual void SetParamStartAddress(ulong);
    virtual void SetProtectionPara(ParameterInfo);
    virtual void SetIsInfoPart(bool);
    virtual void SetInfoArea(int);
    virtual void SetParameterInfoList(const QList<ParameterInfo> &,
                                      const QList<ParameterInfo> &,
                                      const QList<ParameterBuff> &);
    virtual void SetParameterSaveInfo(const QString &, ulong);
    virtual void SetIsParameterReset(bool);
protected:
    static void SetErrorString(BurnCtrl& ctrl, const QString& enStr);
    bool IsEncrypt() const;
protected:
    bool isOpen;
    bool isConnect;
    QMap<int, QString> strFilePathArray;
    int filePathIndex;
    QString strFilePath;
    QString strFileName;
    QString strFileSize;
    ULONGLONG fileSize;
    BYTE pkgNum;

    unsigned char cDataArray[MAX_BUFFER_LEN];
    unsigned int u32DataLen;
    HI_BURN_FSM fsm;
    QFile binFile;
    int progressPos;
    BootType bootType;
    QString interruptFlag;
    bool isGetRandomData;
    bool burnflag;
    int baud;       // 波特率
    int com;        // 串口号
    QSerialPort::Parity parity;    // 校验
    int databits;   // 数据位
    int stopbits;   // 停止位
    int flowctrl;    // 流控
    PortManager port; // CSerialPort类对象
    QString ipAddr;
    unsigned int ipPort;
    static CSLock csLock;
    static QMap<UINT, BurnCtrl *> sendCtrlTimerToPoint;
    static QMap<UINT, const BurnCtrlTimer::TimerInfo *> timerToParam;
    UINT sendCtrlTimerID;
    HANDLE timerQueue;
    int sendCtrlCount;
    UINT commonTimerID;
    UINT sendBurnTimeout;
    int ctrlPeriod;
    DWORD commEvents;
    BurnDlg::BurnDlg *burnDlg;
    bool isSecConn;

    bool isAutoBurn;
    bool isLoaderDfu;
    DfuBurnMode dfuMode;
    bool isAutoDisconnect;
    bool isReopenCom;
    UINT isOneTimeBurn;
    bool isResetAfterSuccess;
    bool isSwitchAfterLoader;
    QStringList burnCmdArray;
    QMap<int, BurnCmdType> burnCmdTypeArray;
    int ackFlag;
    int burnCmdIndex;
    unsigned int result;
    bool isProcessOk;
    bool isForceReadWithSleep;
    bool isResultByOwner;
    unsigned int forceReadTime;
    UINT retryTime;
    UINT connectConfirmSleepTimeout;
    UINT connectConfirmWaitTimeout;
    UINT connectConfirmMaxTime;
    UINT connectConfirmTime;
    bool onlyBurnToolLog;
    bool independent = false;
    unsigned int totalNum = 20;
    unsigned int numPerLine = 10;
    bool isReset;
    bool isExport;
    QString exportTarget;
    QString exportAddr;
    QString exportSize;

    bool isShutDown;
    bool isWiteThreadAlive;
    HANDLE witeThread;
    DWORD witeThreadId;
    long int witeThreadMsgId;
    CRITICAL_SECTION communicationSync;
    CRITICAL_SECTION csEdit;
    CRITICAL_SECTION csSend;
    bool isExactTimer;
    int burnFileSize;
    CRITICAL_SECTION csLog;
    unsigned int modemPacketSize;
    unsigned int modemPacketSizeBackup;
    UINT oneBurnTime;
    QMap<int, BIN_INFO> infoArray;
    BurnCtrlWorkerClass::BurnCtrlWorker *worker;
    MyThreadClass::MyThread *thread;
    QTimer *startConnectTimer;
    QTimer *commonTimer;
    U32 commonTimerEvent;
    bool isOnlyEraseAll;
    int isEraseMode;
    QStringList burnFileName;
    QMutex myMutex;
    bool isMultipleBurn;
    ChipType chipType;
    BOOL isCancel;
    QMap<int, BIN_INFO> infoArrayDlg;
    bool isFirstBurnStart;
    HidDeviceInfo deviceInfo;
    HidDeviceInfo hidDeviceInfo;
    OperationLog *optLog;
    bool isEncrypt;
    MemoryOperation memoryOperation;
    BYTE *encryptBuffer;
    DWORD encryptBufferLen;
    bool readEfuse;
    QString startBit;
    QString bitWidth;
    int chipModel;
    McuConfig mcuConfig;
    int transmissionMode;
    McuJtagSwd mcuJtagSwdPath;
    McuChipId mcuChipIdInfo;
    MainStartAddrInfo mainStartAddrInfo;
    SramAddrInfo sramAddrInfo;
    QString burnPath;
    bool isReadBack;
    bool isRun;
    ProductVersionClass::ProductVersion product;
    QString serialName;
    IPInfo ipInfo;
    QString ipAddress;
    ulong infoStartAddress;
    unsigned int eraseConfig;
    QVector<EraseConfig> vecEraseConfig;
    MyStringClass::StringClass stringClass;
    Base::PORT_INDEX portType = Base::MIN_PORT;
    QStringList m_eraseModeStr;
    QString fwpkgVersion;
    SingleLineWritingInfo singleLineWritingInfo;
};
#endif
